﻿using System;
using System.Net;
using System.Net.Sockets;
using Tools.Debugging;
using System.Text;

namespace repliback4.Net.ClientSide {
    public class Client {
        public delegate void OnConnectedHandler ( );
        public event OnConnectedHandler OnConnected;
        public Server server;
        public Client ( ) {
            Logger.Created( this );
        }
        public void Connect ( String address, int port ) {
            Logger.Debug( this, "Connecting to {0}:{1}...", address, port );
            IPAddress addr;
            if ( IPAddress.TryParse( address, out addr ) ) {
                this.Connect( addr, port );
            } else {
                try {
                    Logger.Debug( this, "trying to resolve address.." );

                    IPHostEntry hostEntry = Dns.GetHostEntry( address );
                    Logger.Debug( this, "resolved: ", hostEntry.AddressList );

                    this.Connect( hostEntry.AddressList, port );
                } catch ( Exception e ) {
                    Logger.Exception( this, "Connect", e );
                    throw e;
                }
            }
        }

        public void Connect ( IPEndPoint endpoint ) {
            this.Connect( endpoint.Address, endpoint.Port );
        }
        protected void Connect ( IPAddress address, int port ) {
            this.Connect( new IPAddress[] { address }, port );
        }
        protected void Connect ( IPAddress[] addresses, int port ) {
            Logger.Debug( this, "Connecting..." );
            TcpClient client = new TcpClient( );
            client.BeginConnect( addresses, port, new AsyncCallback( this.OnConnect ), client );
        }
        private void OnConnect ( IAsyncResult result ) {
            try {
                TcpClient client = ( TcpClient ) result.AsyncState;
                client.EndConnect( result );

                if ( client.Connected ) {
                    this.server = new Server( this, client );
                    if ( this.OnConnected != null ) this.OnConnected( );
                } else {
                    throw new Exception( "Client not conneted" );
                }
            } catch ( SocketException e ) {
                switch ( e.SocketErrorCode ) {
                    case SocketError.ConnectionRefused:
                        Logger.Debug( this, "!!! Connection refused" );
                        break;
                    default:
                        Logger.Exception( this, "OnConnect: SocketException", e );
                        break;
                }

            } catch ( Exception e ) {
                Logger.Exception( this, "OnConnect: Exception", e );
            }
        }

    }
}
